<?php
/**
 * Created by PhpStorm.
 * User: skytop
 * Date: 2017/1/23
 * Time: 13:28
 */
//[使用数组]

#数组:一个可以存储一组或一系列数组的变量;一个数组可以具有许多个元素,每个元素有一个值,一个包含其他数组的数组称为多维数组
#PHP支持数字索引数组和关联数组.

/*[主要内容]
 * 1.数字索引数组
 * 2.非数字索引数组
 * 3.数组操作符
 * 4.多维数组
 * 5.数组排序
 * 6.数组函数
 * */

//数字索引数组的初始化
#1.$products=array();或者$products=[];
$products=array();
#2.升序排列数字的数组:可用函数range()-------建立一个包含指定范围单元的数组;
##array range(mixed $start,mixed $limit[,number $step=1])[mixed为可接受不同类型,即类型未定]
/*[参数]
 *start:序列的第一个值
 *limit:序列结束于limit值
 *step:如果给出了step的值,它将被作为单元之间的步进值.step应该为正值.如果未指定,step则默认为1
 *
 *[返回值]
 *返回的数组中从start到limit的单元,包括它们本身
 * */
$number=range(1,10);
$number_step=range("a","z",3);
var_dump($number,$number_step);

//访问数组的内容
#$variable[key]

//使用循环访问数组
/*for($i=0;$i<10;$i++){
    echo $products[$i];
}*/

foreach($number as $key=>$current){
    echo $current."---".$key."<br/>";
}
echo "<hr/>";

######################################
//[关联数组]
//使用不同索引的数组
#1.初始化关联数组
$prices=array("Tires"=>100,"Oil"=>10,"Spark Plugs"=>4);
#访问数组
echo $prices['Tires']."<hr/>";

//使用循环语句
#因为关联数组的索引不是数字,因此无法在for循环语句中使用一个简单的计数器对数组进行操作
#但可以使用foreach循环或者list()和each()结构
foreach($prices as $key=>$val){
    echo $key."=====".$val."<br/>";
}
/*foreach($prices as $key=>$val){
    echo $key."=====".$val."<br/>";
}*/

//each
//返回数组中当前的键/值对并将数组指针向前移动一步
#array each(array &$array)
/*在执行each()之后,数组指针将停留在数组中的下一个单元或者当碰到数组结尾时停留在最后一个单元,如果要再用each遍历数组,必须使用reset()
 *
 * [返回值]
 * 返回array数组中当前指针位置的键/值对并向前移动数组指针.
 * 键值对被返回为四个单元的数组,键名为0,1,key和value.
 * 单元0和key包含有数组单元的键名,1和value包含有数据.
 *
 * 如果内部指针越过了数组的末端,则each()返回FALSE
 * */
reset($prices);
var_dump(each($prices));


//list---(并非函数,而是语法结构).list()用一步操作给一组变量进行赋值
//把数组中的值赋给一些变量
#array list(mixed $varname[,mixed $...]) | 返回指定的数组
$info=array("coffee","brown","caffeine");

//列出所有变量
list($drink,$color,$power)=$info;
echo "$drink is $color and $power makes it special.";
echo "<hr/>";
reset($prices);

//list+each组合来实现遍历数组,但是要reset()重置数组指针位置
while(list($key,$value)=each($prices)){
    echo $key."++++++++++".$value."<br/>";
}

echo "<hr/>";

//数组操作符
//只有一个特殊的操作符集适用于数组.这个集合中的大多数操作符都有与之对应的标量操作符.
#1.+(联合)
#2.==(等价)
#3.===(恒等)
#4.!=(不等价) | <>
#5.!==(不恒等)
#

//多维数组
$productsD=array(
    array('TIR','Tires',100),
    array('OIL','Oil',10),
    array('SPK','Spark Plugs',4)
);

for($row=0;$row<3;$row++){
    for($column=0;$column<3;$column++){
        echo "|".$productsD[$row][$column];
    }
    echo "<br/>";
}

echo "<hr/>";

//while each() list()
for($row=0;$row<3;$row++){
    while(list($key,$value)=each($productsD[$row])){
        echo "|$value";
    }
    echo "<br/>";
}

//三维数组具有高,宽,深的概念.如果二位数组为一个表格,则三维数组为一堆这样的表格


//数组排列
//对保存在数组中的相关数据进行排序是一件非常有意义的事情.使用并且排序一个一维数组是非常简单的.

//使用sort()函数
//对数组排序regular
#bool sort(array &$array[,int $sort_flags=SORT_REGULAR])
/*本函数对数组进行排序.当本函数结束时数组单元将被从最低到最高重新安排
 *[参数]
 * array:要排序的数组
 * sort_flags:可选的第二个参数sort_flags可以用以下值改变排序的行为:
 *  排序类型标记:
 *      1.SORT_REGULAR:正常比较单元(不改变类型)
 *      2.SORT_NUMERIC:单元被作为数字来比较
 *      3.SORT_STRING:单元被作为字符串来比较
 *      4.SORT_LOCALE_STRING:根据当前的区域(locale)设置来把单元当作字符串比较,可以用setlocale()来改变.
 *      5.SORT_NATURAL:和natsort()类似对每个单元以"自然的顺序"对字符串进行排序.(PHP5.4新增)
 *      6.SORT_FLAG_CASE:能够与SORT_STRING或SORT_NATURAL合并(OR位运算),不区分大小写排序字符串
 *
 * [返回值]
 * 成功时返回true反之为false
 * */
$fruits=array('le1mon','or2ange','ba3nana','ap4ple');
echo "<hr/>";
echo "默认结果:";
sort($fruits);var_dump($fruits);
echo "SORT_REGULAR结果:";
sort($fruits,SORT_REGULAR);var_dump($fruits);
echo "SORT_STRING结果:";
sort($fruits,SORT_STRING);var_dump($fruits);
echo "SORT_NUMERIC结果:"; //不知道为啥不一样的排序
sort($fruits,SORT_NUMERIC);var_dump($fruits);
echo "SORT_NATURAL结果:";
sort($fruits,SORT_NATURAL);var_dump($fruits);

echo "<hr/>";

//使用asort()函数和ksort()函数对关联数组排序
//函数asort()是根据数组的每个元素进行排序的

#asort()
//对数组进行排序并保持索引关系
//&$array说明为引用赋值,也就是这个函数改变原有变量
#bool asort(array &$array[,int $sort_flags=SORT_REGULAR])
//本函数对数组进行排序,数组的索引保持和单元的关联.主要用于对那些单元顺序很重要的结合数组进行排序.
/*[参数]
 * array:输入的数组
 * sort_flags:可以用可选的参数sort_flags改变排序的行为[同sort()函数]
 *
 *[返回值]
 * 成功时返回true,反之为false
 * */
$fr=array("d"=>"lemon","a"=>"orange","b"=>"banana","c"=>"apple");
$res=asort($fr);echo "asort():";var_dump($res,$fr);

echo "<hr/>";

//ksort()
//对数组按照键名排序
//参数及返回值同asort()
ksort($fr);echo "ksort():";var_dump($fr);


//反向排序
#你已经了解了sort(),asort()和ksort().这三个不同的排序函数都使数组按升序排序.它们每个都对应有一个反向排序的函数,可以将数组按降序排序
#它们为rsort(),arsort()和krsort()
#反向排序函数与排序函数的用法相同.
krsort($fr);
echo "对数组按照键名反向排序:";var_dump($fr);


//多维数组的比较

//用户自定义比较
#usort()
//使用用户自定义的比较函数对数组中的值进行排序
#bool usort(array &$array,callable $cmp_function)
//本函数经用用户自定义的比较函数对一个数组中的值进行排序.如果要排序的数组需要用一种不寻常的标准进行排序,那么应该使用此函数
#此函数返回的排序为升序排序
$pd=array(
    array('TIR','Tires',100),
    array('OIL','Oil',10),
    array('SPK','Spark Plugs',4)
);

function compare($x,$y){
    if($x[1]==$y[1]){
        return 0;
    }else if($x[1]<$y[1]){
        return -1;
    }else{
        return 1;
    }
}
usort($pd,'compare');var_dump($pd); //原来是元素进行对比,然后排序

//按价格排序(从小到大)
function price($x,$y){
    if($x[2]==$y[2]){
        return 0;
    }else{
        return ($x[2]<$y[2])?-1:1;
    }
}
usort($pd,'price');var_dump($pd);

//uasort()和uksort()
#对于前面的u代表user为用户自定义排序.此类函数当为简单的数字或文本为数组值时就使用asort()或ksort()--------'一维数组',在多维数组则自定义排序按值/键排序

//反向用户排序,当然usort()没有像一维数组排序那样加上r可以反向排序,用户排序直接改变比较函数的返回值反向排序


//对数组进行重新排序
#shuffle()
//将数组打乱
#bool shuffle(array &$array)
$pictures=array('tire.jpg','oil.jpg','spark_plug.jpg','door.jpg','steering_wheel.jpg');
shuffle($pictures);var_dump($pictures);

#array_reverse()
//返回一个单元顺序相反的数组
#array array_reverse(array $array[,bool $preserve_keys=false])
//array_reverse()接受数组array作为输入并返回一个单元为相反顺序的新数组
/*[参数]
 * array:输入的数组
 * preserve_keys:如果设置为true会保留数字的键.非数字的键则不受这个设置的影响,总是会被保留
 *
 *[返回值]
 * 返回反转后的数组
 * */
echo "<hr/>array_reverse()函数:";
$numbers=range(1,10);var_dump(array_reverse($numbers));echo "preserve_keys的作用:";var_dump(array_reverse($numbers,true));

#array_push()
//将一个或多个单元压入数组的末尾(入栈)-----array_push()将array当成一个栈,并将传入的变量压入array的末尾
#int array_push(array &$array,mixed $var[,mixed $...])
//返回处理后数组的元素个数
$numbers=array();
for($i=10;$i>0;$i--){
    echo array_push($numbers,$i)."<br/>";
}
var_dump($numbers); //从末尾添加,顺序$i=10,9,8,7,6,...

#array_pop()-------与array_push()相反
//将数组最后一个单元弹出(出栈)
#mixed array_pop(array &$array)
//array_pop()弹出并返回array数组的最后一个单元,并将数组array的长度减一.如果array为空(或者不是数组)将返回null.此外如果被调用不是一个数则会产生一个Warning
//Note:使用此函数会重置(reset())array指针
//返回值:返回array的最后一个值.如果array是空(如果不是一个数组),将会返回null
$stack=array('a'=>'orange','b'=>'banana','c'=>'apple','d'=>'respberry');
$fruit=array_pop($stack);
var_dump($fruit,$stack);


################################################
//php排序???(冒泡排序)[面试可能要用,还是看看吧]   ###
################################################

//数组指针函数
//each(),current(),reset(),end(),next(),pos()和prev()

#current()-------别名pos()
//返回数组中的当前单元
#mixed current(array &$array)
//每个数组中都有一个内部的指针指向它"当前的"单元,初始指向插入到数组中的第一个单元
//返回值:current()函数返回当前被内部指针指向的数组单元的值,并不移动指针.如果内部指针指向超出了单元列表的末端,current()返回false
//Warning:此函数可能返回布尔值false,但也可能返回等同于false的非布尔值
echo "<hr/>数组指针函数演示:<br/>";
$transport=array('foot','bike','car','plane');
echo current($transport);

//next()与each()
//each()在前面已经有了,是先返回当前指针位置的元素并将数组指针向前移一位,而next()是先将指针向前移一位再返回当前指针位置的元素

//next()
//将数组中的内部指针向前移动一位
#mixed next(array &$array)
//返回值:返回数组内部指针指向的下一个单元的值,或当没有更多单元时返回FALSE
echo next($transport);

//reset
//将数组的内部指针指向第一个单元
#mixed reset(array &$array)
//reset()将array的内部指针倒回到第一个单元并返回第一个数组单元的值
echo reset($transport);

//end
//将数组的内部指针指向最后一个单元
#mixed end(array &$array)
//end()将array的内部指针移动到最后一个单元并返回其值
//返回值:返回最后一个元素的值,或者如果是空数组则返回FALSE
echo end($transport);

//prev()
//将数组的内部指针倒回一位
#mixed prev(array &$array)
//将数组的内部指针倒回一位.prev()和next()的行为类似,只除了它将内部指针倒回一位而不是前进一位
echo prev($transport);

//array_walk()
//使用用户自定义函数对数组中的每个元素做回调处理
#bool array_walk(array &$array,callback $funcname[,mixed $userdata=NULL])
//将用户自定义函数funcname应用到array数组中的每个单元

//array_walk()不会受到array内部数组指针的影响.array_walk()会遍历整个数组而不管指针的位置

/*[参数]
 * array:输入的数组
 * funcname:典型情况下funcname接受两个参数.array参数的值作为第一个,键名作为第二个
 * note:如果 funcname 需要直接作用于数组中的值，则给 funcname 的第一个参数指定为引用。这样任何对这些单元的改变也将会改变原始数组本身。
 * userdata:如果提供了可选参数userdata,将被作为第三个参数传递给callback funcname
 *
 *[返回值]
 * 成功时返回true,反之为false
 *
 *[错误/异常]
 *  如果 funcname 函数需要的参数比给出的多，则每次 array_walk() 调用 funcname 时都会产生一个 E_WARNING 级的错误。这些警告可以通过在 array_walk() 调用前加上 PHP 的错误操作符 @ 来抑制，或者用 error_reporting()。
 * */

$fruits=array('d'=>'lemon','a'=>'orange','b'=>'banana','c'=>'apple');
function test_alter(&$iteml,$key=null,$prefix){
    $iteml="$prefix:$iteml";
}

array_walk($fruits,'test_alter','fruit');
echo "<hr/>array_walk:";
var_dump($fruits);


//统计数组元素个数
//count(),sizeof()和array_count_values()

//count()-----别名sizeof()
//计算数组中的单元数目或对象中的属性个数------统计一个数组里的所有元素,或者一个对象里的东西
#int count(mixed $var[,int $mode=COUNT_NORMAL])
#对于对象,如果安装了SPL,可以通过实现countable接口来调用count().该接口只有一个方法...
/*[参数]
 * var:数组或者对象
 * mode:如果可选的mode参数设为COUNT_RECURSIVE(或1),count()将递归的对数组计数.对计算多维数组的所有单元尤其有用.mode的默认值为0.count()识别不了无限递归
 *
 *[返回值]
 * 返回var中的单元数目.如果var不是数组类型或者实现了Countable接口的对象,将返回1,有一个列外,如果var是null则结果为0
 *Caution:count()对没有初始化的变量返回0,单对于空的数组也会返回0.用isset()来测试变量是否已经初始化
 * */
echo count($fruits)."<br/>";
echo "递归对数组计数结果:".count($pd,1)."<br/>"."不递归对数组计数结果:".count($pd); //对维数组为一维元素个数+后面维度元素个数

//array_count_values()
//统计数组中所有的值出现的次数
#array array_count_values(array $input)
//array_count_values()返回一个数组,该数组用input数组中的值作为键名,该值在input数组中出现的次数作为值
$count_values=array(1,'hello',1,'world','hello');
echo "统计数组中所有的值出现的次数";
var_dump(array_count_values($count_values));
//错误/异常:对数组里面的每个不是string和integer类型的元素跑出一个警告错误(E_WARNING)

//将数组转换成标量变量
#extract()
//从数组中将变量导入到当前的符号表
#int extract(array &$var_array[,int $extract_type=EXTR_OVERWRITE[,string $prefix=NULL]])
//本函数用来将变量从数组中导入到当前的符号表中
//检查每个键名看是否可以作为一个合法的变量名,同时也检查和符号表中已有的变量名的冲突
/*[参数]
 * var_array:
 *  一个关联数组.此函数会将键名当做变量名,值作为变量的值.对每个键/值对都会在当前的符号表中建立变量,并受到extract_type和prefix参数的影响
 *  必须使用关联数组,数字索引数组将不会产生结果,除非用了EXTR_PREFIX_ALL或者EXTR_PREFIX_INVALID
 *
 * extract_type:
 *  对待非法/数字和冲突的键名的方法将根据extract_type参数决定.可以是一下值之一:
 *      EXTR_OVERWRITE:如果有冲突,覆盖已有的变量
 *      EXTR_SKIP:如果有冲突,不覆盖已有的变量
 *      EXTR_PREFIX_SAME:如果有冲突,在变量名前加上前缀prefix
 *      EXTR_PREFIX_ALL:给所有变量名加上前缀prefix
 *      EXTR_PREFIX_INVALID:仅在非法/数字的变量名前加上前缀prefix
 *      EXTR_IF_EXISTS:仅在当前符号表中已有同名变量时,覆盖它们的值.其他的都不处理.
 *      EXTR_REFS:将变量作为引用提取.
 *
 * */
$size='large';
$var_array=array('color'=>'blue','size'=>'medium','shape'=>'sphere');
extract($var_array,EXTR_PREFIX_SAME,'wddx');
echo "$color,$size,$shape,$wddx_size";